class ActorManager
{
  // Constants
  static final int PULSE_SPEED = 3;
  static final int COLLISION_BOX = 50;
  static final float ENEMY_DMG = 0.1f;
  static final float PLAYER_DMG = 10;
  
  ArrayList<Enemy> enemies;
  ArrayList<Placeable> placeables;
  ArrayList<Projectile> projectiles;
  PImage barver;
  PImage barhoriz;
  PImage barver_pulse;
  PImage barhoriz_pulse;
  PImage enemyTexture;
  int pulseAlpha = 255;
  boolean pulse = false;
  
  ActorManager()
  {
    enemies = new ArrayList<Enemy>();
    placeables = new ArrayList<Placeable>();
    projectiles = new ArrayList<Projectile>();
    barhoriz = loadImage("barricade.png");
    barver = loadImage("barricade1.png");
    barhoriz_pulse = loadImage("barricade_pulse.png");
    barver_pulse = loadImage("barricade1_pulse.png");
    enemyTexture = loadImage("enemy.png");
  }
  
  
  void addEnemy(float y)
  {
    enemies.add(new Enemy(y));
  }
  
  void addProjectile(float x, float y)
  {
    projectiles.add(new Projectile(x, y)); 
  }
  
  void addPlaceable(boolean rot, float x, float y)
  {
    placeables.add(new Placeable(rot, x, y));
  }
  
  void Render()
  {
    //Render projectiles
    for(int i = 0; i < projectiles.size(); ++i)
    {
      Projectile projectile = projectiles.get(i);
     
      rect(projectile.getX(), projectile.getY(), 10, 100);
    }
    
    //Render placeables
    for(int i = 0; i < placeables.size(); ++i)
    {
      Placeable placeable = placeables.get(i);
      
      if(placeable.getBarHz())
      {
        tint(255, placeable.getAlpha());
        image(barhoriz, placeable.getX(), placeable.getY());
        tint(255, pulseAlpha);
        image(barhoriz_pulse, placeable.getX(), placeable.getY());
      }
      else
      {
        tint(255, placeable.getAlpha());
        image(barver, placeable.getX(), placeable.getY());
        tint(255, pulseAlpha);
        image(barver_pulse, placeable.getX(), placeable.getY());
      }
      
      fill(255, 0, 0);
      textSize(32);
      //text("Barricades placed: " + placeables.size(), 400, 50);
      textSize(10);
      //text("Health:" + placeable.getHealth(), placeable.getX(), placeable.getY()+ 45);
      
      
    }
    //Render enemies
    for(int i = 0; i < enemies.size(); ++i)
    {
      Enemy enemy = enemies.get(i);
      
      // Render enemy
      //rect(enemy.getX(), enemy.getY(), 20, 20);
      tint(255,255);
      image(enemyTexture, enemy.getX(), enemy.getY());
      
      //Render enemy health count
      textSize(12);
      fill(255);
      //text("health"+enemy.getHealth(), enemy.getX(), enemy.getY());
      
      // Render enemy count
      fill(255, 0, 0);
      textSize(32);
      //text("Enemies: " + enemies.size(), 200, 50);
    }
  }
  
  void Update()
  {
    //Handle state
    if(waveFinished)
    {
      waveFinished = false;
    }
    if(enemies.size() == 0 && waveStarted)
    {
      waveFinished = true;
    }
    
    // Handle projectiles
    for(int i = 0; i < projectiles.size(); ++i)
    {
      Projectile projectile = projectiles.get(i);
      
      // Update
      projectile.Update();
      
      // Check collision with enemies
      for (int j = 0; j < enemies.size(); ++j)
      {
         Enemy enemy = enemies.get(j);
         
         if(projectile.getX() > enemy.getX() && projectile.getX() < enemy.getX() + COLLISION_BOX
           && projectile.getY() > enemy.getY() && projectile.getY() < enemy.getY() + COLLISION_BOX)
         {
           enemy.looseHealth(PLAYER_DMG);
         }
      }
    }
    
    //Handle enemies
    for(int i = 0; i < enemies.size(); ++i)
    {
      Enemy enemy = enemies.get(i);
      int count = placeables.size();
      int index = int(random(0, count));
      
      if(enemy.getY() > height)
      {
        money -= 1;
        enemies.remove(i);
      }
      
      // Give target if there are barricades present
      if(!enemy.hasTarget && placeables.size() > 0)
      {
        enemy.setTargetX(placeables.get(index).getX());
        enemy.setTargetY(placeables.get(index).getY());
        enemy.setHasTarget(true);
      }
      else if(placeables.size() <= 0)
      {
        enemy.setTargetY(height);
        enemy.setTargetX(random(0, width));
      }
      
        enemy.Update();
        if(enemy.getHealth() <= 0)
        {
          enemies.remove(i);
        }
    }   
    // handle placeables
    for(int i = 0; i < placeables.size(); ++i)
    {
      Placeable placeable = placeables.get(i);
      placeable.Update();
      
      //enemy collision with placeable
      for(int j = 0; j < enemies.size(); ++j)
      {
        Enemy enemy = enemies.get(j);
        if(enemy.getX() < placeable.getX() + COLLISION_BOX && enemy.getX() > placeable.getX() - COLLISION_BOX
           && enemy.getY() > placeable.getY() - COLLISION_BOX && enemy.getY() < placeable.getY() + COLLISION_BOX)
        {
          placeable.looseHealth(ENEMY_DMG);
        }
      }
      //Check if target is existing
      for(int j = 0; j < enemies.size(); ++j)
      {
        Enemy enemy = enemies.get(j);
        if(enemy.getX() < placeable.getX() + COLLISION_BOX && enemy.getX() > placeable.getX() - COLLISION_BOX
           && enemy.getY() > placeable.getY() - COLLISION_BOX && enemy.getY() < placeable.getY() + COLLISION_BOX)
        {
          if(placeable.getHealth() <= 0)
          {
            enemy.setHasTarget(false);
          }
        }
      }

      
      //remove if destroyed
    if(placeable.getDeadTimer() <= 0)
      {
        placeables.remove(i);
      }
    }
    
    
    // Adjust barricade pulse
    // Flag for pulsation rhytm
    if (pulseAlpha >= 255)
    {
       pulse = false;
    }
    else if (pulseAlpha <= 30)
    {
       pulse = true;
    }
    
    // Increase light if pulse is flagged
    if(pulse)
      pulseAlpha += PULSE_SPEED;
    // Decrease
    else if(!pulse)
      pulseAlpha -= PULSE_SPEED;
    
  }
}
